﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using FlaUI.Core.AutomationElements;
using FlaUI.Core.Definitions;
using QQTools.Data.Enums.InviteGroup;
using QQTools.Data.Repositories.InviteGroup;
using QQTools.Utils;
using System.Windows.Forms;
using QQTools.Data.Models;
using QQTools.Logging;
using System.Windows.Interop;
using QQTools.Data.Plus;
using Newtonsoft.Json.Linq;


namespace QQTools.Services
{

    class InviteGroupServices
    {
        private readonly InviteGroupRepository _inviteGroupRepository;
        private readonly InviteGroupQQRepository _inviteGroupQQRepository;
        private readonly MainForm _form;

        public InviteGroupServices(MainForm form,
            InviteGroupRepository inviteGroupRepository,
            InviteGroupQQRepository inviteGroupQQRepository)
        {
            _form = form;
            _inviteGroupRepository = inviteGroupRepository;
            _inviteGroupQQRepository = inviteGroupQQRepository;
        }
        /// <summary>
        /// 邀请进群
        /// </summary>
        /// <param name="invitedQQ">被邀请人</param>
        /// <param name="inviteInterval">邀请间隔</param>
        /// <param name="inviteTotal">邀请总数量</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Start(String invitedQQ, int inviteInterval, int inviteTotal, CancellationToken cancellationToken)
        { // string inviterQQ, 
            try
            {
                // 更新状态栏
                _form.UpdateStatusStrip("开始执行邀请任务");
                string msg = string.Empty;
                List<InviteGroupQQModel> inviteQQs = await _inviteGroupQQRepository.GetAllAsync();
                // 1.遍历邀请人列表
                foreach (var qqItem in inviteQQs)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        LogManager.Info("[邀请群] 倒计时任务已取消");
                        break;
                    }

                    // 默认被屏蔽人的qq在线
                    bool qqIsOnline = true;
                    string inviterQQ = qqItem.QQ;
                    // UI更新任务:QQ列表, 并将当前QQ高亮
                    _form.UpdateListViewInviteGroupQQ(qq: inviterQQ);

                    // 判断当前QQ是否已经满足条件
                    if (qqItem.InviteSuccessCount >= inviteTotal)
                    {
                        LogManager.Info($"[邀请群] QQ;{qqItem.QQ} 已成功邀请:{qqItem.InviteSuccessCount} 个群, 切换下一个QQ");
                        _form.UpdateStatusStrip($"[邀请群] QQ;{qqItem.QQ} 已成功邀请:{qqItem.InviteSuccessCount} 个群, 切换下一个QQ");
                        continue;
                    }



                    // 4.循环从群聊数据表中拿出一条,开始邀请:被邀请名单的qq
                    InviteGroupModel inviteGroupTask = await _inviteGroupRepository.GetAndLockNextInviteGroupAsync(inviterQQ);
                    // 获取总群数量
                    int totalGroup = await _inviteGroupRepository.GetCountByQQAsync(inviterQQ);
                    // 已经邀请成功的群数量
                    // int inviteSuccessCount = qqItem.InviteSuccessCount;
                    while (inviteGroupTask != null)
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            LogManager.Info("[邀请群] 倒计时任务已取消");
                            break;
                        }

                        // 判断当前QQ是否已经满足条件
                        if (qqItem.InviteSuccessCount >= inviteTotal)
                        {
                            LogManager.Info($"[邀请群] QQ;{qqItem.QQ} 已成功邀请:{qqItem.InviteSuccessCount} 个群, 切换下一个QQ");
                            break;
                        }


                        msg = $"[邀请进群] QQ:{inviterQQ} 邀请QQ:{invitedQQ} 加入群:{inviteGroupTask.GroupNumber}";
                        LogManager.Info(msg);
                        // UI更新:状态栏
                        _form.UpdateStatusStrip(msg);
                        // UI更新任务:群列表状态,并将当前群号高亮
                        _form.UpdateListViewInviteGroup(inviteGroupTask);

                        var result = await InviteAddGroupProcess(inviteGroupTask.GroupNumber, inviterQQ, invitedQQ, cancellationToken);
                        if (result == InviteAddGroupResult.Success)
                        {


                            // 邀请成功数量+1
                            qqItem.InviteSuccessCount++;
                            // 更新数据库:InviteQQ的InviteSuccessCount自增1
                            await _inviteGroupQQRepository.IncrementInviteSuccessCountAsync(inviterQQ);

                            // 更新数据库:InviteGroup状态为邀请完成
                            await _inviteGroupRepository.UpdateStatusByQQAndGroupNumberAsync(inviterQQ, inviteGroupTask.GroupNumber, InviteGroupStatus.Success);

                            msg = $"[邀请进群] 邀请成功 QQ:{inviterQQ} 邀请QQ:{invitedQQ} 加入群:{inviteGroupTask.GroupNumber}";
                            inviteGroupTask.Status = InviteGroupStatus.Success;


                        }
                        else
                        {
                            // 邀请失败次数+1
                            qqItem.InviteNumber++;
                            // 更新数据库:InviteQQ的InviteNumber自增1
                            await _inviteGroupQQRepository.IncrementInviteNumberAsync(inviterQQ);

                            if (result == InviteAddGroupResult.QQOffline)
                            {
                                // 设置为离线状态
                                qqIsOnline = false;
                                inviteGroupTask.Status = InviteGroupStatus.Failed;
                            }
                            else
                            {
                                msg = $"[邀请进群] 邀请失败 QQ:{inviterQQ} 邀请QQ:{invitedQQ} 加入群:{inviteGroupTask.GroupNumber} 原因:{result.ToString()}";
                                inviteGroupTask.Status = InviteGroupStatus.Failed;
                            }
                        }

                        // 获取邀请成功的群总数量
                        // qqItem.InviteSuccessCount = await _inviteGroupRepository.GetCountByQQAndStatusAsync(inviterQQ, InviteGroupStatus.Success);


                        // 保存QQ列表进度
                        await _inviteGroupQQRepository.UpdateAsync(qqItem);
                        // 保存群列表进度
                        await _inviteGroupRepository.UpdateAsync(inviteGroupTask);

                        // UI更新任务:QQ列表状态, 并将当前QQ高亮
                        _form.UpdateListViewInviteGroupQQ(qq: inviterQQ);
                        // UI更新任务:群列表状态,并将当前群号高亮
                        _form.UpdateListViewInviteGroup(inviteGroupTask);

                        // 更新状态栏
                        _form.UpdateStatusStrip(msg);
                        LogManager.Info($"{msg} 距离下一次邀请还剩: {inviteInterval} 秒");
                        await _form.StartCountdown($"{msg} 距离下一次邀请还剩:", inviteInterval, cancellationToken, $"{msg} 任务停止", null);


                        if (qqIsOnline == false)
                        {
                            // 如果qq离线,则跳出循环, 切换到下一个qq
                            LogManager.Info($"[邀请群] QQ:{inviterQQ} 离线退出邀请群, 继续下一个QQ");
                            break;
                        }

                        // 获取下一条群聊数据
                        inviteGroupTask = await _inviteGroupRepository.GetAndLockNextInviteGroupAsync(inviterQQ);
                        Console.WriteLine("邀请任务还在进行中...............................................");
                    }

                    // 获取已经邀请的群总数量
                    qqItem.InviteSuccessCount = await _inviteGroupRepository.GetCountByQQAndStatusAsync(inviterQQ, InviteGroupStatus.Success);

                    string txt = $"[邀请群]  进度:{qqItem.InviteSuccessCount}/{inviteTotal}  QQ:{inviterQQ} 邀请任务已完成";
                    if (qqIsOnline == false)
                    {
                        // qq离线, 切换到下一个qq
                        txt = $"[屏蔽群] 进度:{qqItem.InviteSuccessCount}/{inviteTotal}  QQ:{inviterQQ} 离线退出邀请群, 继续下一个QQ";
                    }

                    LogManager.Info(txt);
                    // 更新状态栏
                    _form.UpdateStatusStrip(txt);
                }

                // 说明邀请任务已经结束
                // MessageBox.Show($"[邀请进群] 邀请任务已经结束", "提示");

                //InviteAddGroupProcess(inviteGroup.GroupNumber, inviterQQList, invitedQQ); // 486487978

                //InviteAddGroupProcess("87350353", "3377989884", "505078565"); // 486487978
            }
            catch (OperationCanceledException)
            {
                LogManager.Info("[邀请进群] 任务被用户取消");
                //_form.UpdateStatusStrip("任务被用户取消");
            }
            catch (Exception ex)
            {
                LogManager.Error("[邀请进群] 发生未处理的异常", ex);
                //_form.UpdateStatusStrip("任务发生错误，请查看日志");
            }
            finally
            {
                LogManager.Info("[邀请进群] 任务已经结束");
            }
        }

        // 自定义异步重试组件
        public static async Task<T> RetryWhileNullAsync<T>(
            Func<Task<T>> func,
            TimeSpan timeout,
            TimeSpan interval)
        {
            var cts = new CancellationTokenSource(timeout);
            while (!cts.IsCancellationRequested)
            {
                var result = await func(); // 关键异步点
                if (result != null) return result;
                await Task.Delay(interval, cts.Token);
            }
            throw new TimeoutException("重试超时未获取到对象");
        }

        public async static Task<InviteAddGroupResult> InviteAddGroupProcess(string groupUin, string inviterQQ, string invitedQQ, CancellationToken cancellationToken)
        {
            try
            {
                // 关闭其他无关窗口
                CloseOtherWindows();
                // 生成腾讯URL并打开浏览器
                string url = QQPlus.GenerateTencentUrl(groupUin: Convert.ToInt64(groupUin), qqUin: inviterQQ);
                Process.Start(url);
                await Task.Delay(1000);

                int processId = QQPlus.GetQQPid(inviterQQ);
                AutomationElement groupChatWindow = null;

                for (int i = 0; i < 5; i++)
                {
                    groupChatWindow = await QQPlus.GetGroupChatWindowWin32(processId);
                    if (groupChatWindow != null)
                    {
                        break;
                    }
                    await Task.Delay(200, cancellationToken);
                }

                if (groupChatWindow == null)
                {
                    // 检查是否存在安全提醒窗口或添加群窗口
                    if (QQPlus.CheckAndHandleSpecialWindows())
                    {
                        LogManager.Error("[邀请群] 出现安全提醒窗口或添加群窗口");
                        return InviteAddGroupResult.GroupBlockedOrNotAdded;
                    }

                    // 检查是否离线
                    if (QQPlus.CheckQQIsOffline(inviterQQ) == false)
                    {
                        LogManager.Error($"[邀请群] QQ:{inviterQQ} 已离线");
                        return InviteAddGroupResult.QQOffline;
                    }

                    LogManager.Error("[邀请群] 获取群聊窗口失败");
                    return InviteAddGroupResult.GroupNotFound;
                }

                LogManager.Info($"[邀请群] 成功打开群聊, 群号:{groupUin} 群名:{groupChatWindow.Name}");

                // 设置群聊窗口为前台窗口
                Win32Api.SetForegroundWindow(groupChatWindow.Properties.NativeWindowHandle);

                await Task.Delay(1500);
                // 检查有没有 公告弹窗
                //if (await QQAuto.CloseNoticeDialog‌Windows(groupChatWindow)) {
                //    LogManager.Info("[屏蔽群] 出现 公告弹窗");
                //    await Task.Delay(1500);
                //}


                // 点击“邀请新成员”按钮
                AutomationElement btnInviteNewFriend = FlauiAuto.FindControl(groupChatWindow, ControlType.Button, "邀请新成员");
                if (btnInviteNewFriend == null || !btnInviteNewFriend.Properties.IsEnabled.Value)
                {
                    LogManager.Error("[邀请好友进群] 点击 邀请新成员 按钮失败");
                    return InviteAddGroupResult.OpenWindowFailed;
                }

                btnInviteNewFriend.Click();
                await Task.Delay(1000);

                // 动态等待邀请进群窗口加载
                // await WaitForConditionAsync(() => QQAuto.GetInviteAddGroupWindow(groupChatWindow) != null, TimeSpan.FromSeconds(5));
                AutomationElement inviteAddGroupWindow = null;

                for (int i = 0; i < 10; i++)
                {
                    inviteAddGroupWindow = QQPlus.GetInviteAddGroupWindow(groupChatWindow);
                    if (inviteAddGroupWindow != null)
                    {
                        break;
                    }
                    await Task.Delay(200, cancellationToken);
                }

                if (inviteAddGroupWindow == null)
                {
                    LogManager.Error("[获取群聊窗口] 获取邀请进群窗口失败");
                    return InviteAddGroupResult.OpenWindowFailed;
                }

                SetForegroundWindow(inviteAddGroupWindow);

                // 输入被邀请人QQ号
                AutomationElement inviteSearchInput = FlauiAuto.FindControl(inviteAddGroupWindow, ControlType.Edit, "输入查找关键字");
                if (inviteSearchInput == null)
                {
                    LogManager.Error("[获取群聊窗口] 获取邀请进群输入框失败");
                    return InviteAddGroupResult.OpenWindowFailed;
                }

                await ClearAndSendKeys(inviteSearchInput, invitedQQ);
                await Task.Delay(1000);


                //bool isInvitedFriendFound = await WaitForConditionAsync(
                //    () => {
                //        //invitedFriend = inviteAddGroupWindow.FindFirstByXPath($"//ListItem[contains(@Name, '({invitedQQ})')]");
                //        //if (invitedFriend != null) {
                //        //    return true;
                //        //}
                //        //invitedFriend = inviteAddGroupWindow.FindFirstByXPath($"//ListItem[contains(@Name, '{invitedQQ}@')]");

                //        invitedFriend = GetSelectedSearchResult(inviteAddGroupWindow, invitedQQ);

                //        return invitedFriend != null;
                //    },
                //    TimeSpan.FromSeconds(7));

                // 动态等待被邀请人列表加载
                AutomationElement invitedFriend = null;
                for (int i = 0; i < 10; i++)
                {
                    invitedFriend = GetSelectedSearchResult(inviteAddGroupWindow, invitedQQ);
                    if (invitedFriend != null)
                    {
                        break;
                    }
                    await Task.Delay(500, cancellationToken);
                }


                if (invitedFriend == null)
                {
                    LogManager.Error("[邀请好友进群] 被邀请人未找到");
                    CloseAllWindows(inviteAddGroupWindow, groupChatWindow);
                    return InviteAddGroupResult.InvitedPersonNotFound;
                }

                LogManager.Info("[邀请好友进群] 选择被邀请人");
                invitedFriend.Click();
                await Task.Delay(1000);
                // 判断是不是出现添加失败窗口
                IntPtr intPtr = Win32Api.FindWindow("TXGuiFoundation", "添加失败");
                if (intPtr != IntPtr.Zero)
                {
                    LogManager.Info($"[邀请好友进群] 出现邀请失败窗口, 被邀请人:{invitedQQ} 群聊:{groupUin}");
                    // 先关闭 失败  窗口
                    Win32Api.CloseAllWindows("TXGuiFoundation", "添加失败");
                    CloseAllWindows(inviteAddGroupWindow, groupChatWindow);
                    return InviteAddGroupResult.AddFailedWindow;
                }

                // 点击“确定”按钮
                AutomationElement confirmButton = await FlauiAuto.FindElementByXPathAsync(inviteAddGroupWindow, "//Button[@Name='确定']");
                if (confirmButton == null || !confirmButton.Properties.IsEnabled.Value)
                {
                    LogManager.Info($"[邀请好友进群] 被邀请人:{invitedQQ} 已在群聊:{groupUin}");
                    CloseAllWindows(inviteAddGroupWindow, groupChatWindow);
                    return InviteAddGroupResult.Success;
                }
                await Task.Delay(1000);
                confirmButton.Click();
                LogManager.Info($"[邀请好友进群] 点击确定, 被邀请人:{invitedQQ} 群聊:{groupUin}");
                await Task.Delay(1000);
                IntPtr tix = Win32Api.FindWindow("TXGuiFoundation", "提醒");
                if (tix != IntPtr.Zero)
                {
                    LogManager.Info($"[邀请好友进群] 出现提醒窗口, 被邀请人:{invitedQQ} 群聊:{groupUin}");
                    Win32Api.CloseAllWindows("TXGuiFoundation", "提醒");
                    return InviteAddGroupResult.AddFailedWindow;
                }
                Win32Api.CloseAllQQWindows("提示");

                LogManager.Info("[邀请好友进群] 确认邀请成功, 关闭所有窗口");
                // 关闭所有窗口
                CloseAllWindows(inviteAddGroupWindow, groupChatWindow);
                return InviteAddGroupResult.Success;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[邀请好友进群] 发生异常: {ex.Message}", ex);
                return InviteAddGroupResult.Unknown;
            }
        }

        private static void CloseOtherWindows()
        {
            // 有多个群里会话窗口
            Win32Api.CloseAllQQWindowsEndsWith("个会话");
            // 关闭安全提醒窗口
            // 关闭提示窗口
            // 需要关闭的窗口标题数组
            string[] titles = { "安全提醒", "提示" };
            Win32Api.CloseAllQQWindows(titles);
        }

        private static AutomationElement GetSelectedSearchResult(AutomationElement inviteAddGroupWindow, string invitedQQ)
        {
            if (inviteAddGroupWindow == null)
            {
                LogManager.Error("[GetSelectedSearchResult] 获取邀请进群窗口失败");
                return null;
            }

            // 预先计算匹配字符串
            string search1 = $"({invitedQQ})";
            string search2 = $"{invitedQQ}@";

            AutomationElement[] selectItems = inviteAddGroupWindow.FindAllDescendants(cf => cf.ByControlType(ControlType.ListItem));

            foreach (AutomationElement item in selectItems)
            {
                if (item == null) continue;

                // 检查Name属性是否存在且有效
                if (!item.Properties.Name.IsSupported) continue;

                string name = item.Name;
                if (string.IsNullOrEmpty(name)) continue;

                if (name.Contains(search1) || name.Contains(search2))
                {
                    Console.WriteLine(item.ToString());
                    try
                    {
                        return item;
                    }
                    catch (Exception ex)
                    {
                        LogManager.Error($"点击列表项失败: {ex.Message}");
                    }
                }
            }
            return null;
        }

        private static async Task<bool> WaitForConditionAsync(Func<bool> condition, TimeSpan timeout)
        {
            DateTime deadline = DateTime.Now.Add(timeout);
            while (DateTime.Now < deadline)
            {
                if (condition())
                {
                    return true;
                }
                await Task.Delay(200);
            }
            return false;
        }

        private static void SetForegroundWindow(AutomationElement window)
        {
            if (window != null && !window.Properties.IsOffscreen.Value)
            {
                IntPtr value = window.Properties.NativeWindowHandle.Value;
                if (!Win32Api.SetForegroundWindow(value))
                {
                    LogManager.Info($"[邀请好友进群] 置顶窗口失败, handl: {window.Name}");
                }
                LogManager.Info($"[邀请好友进群] 置顶窗口成功: {window.Name}");
            }
            else
            {
                LogManager.Info("[邀请好友进群] 置顶窗口失败: 窗口为空或窗口已离屏");
            }
        }

        private static async Task ClearAndSendKeys(AutomationElement element, string keys)
        {
            if (element != null)
            {
                LogManager.Info($"[ClearAndSendKeys] 清空输入框并输入: {keys}");
                await Task.Delay(1000);
                element.Click();
                await Task.Delay(500);
                SendKeys.SendWait("^a"); // Ctrl+A选中所有文本
                SendKeys.SendWait("{DEL}"); // 删除选择的文本
                await Task.Delay(100);
                SendKeys.SendWait(keys);
                await Task.Delay(1000);

            }
        }

        private static void CloseAllWindows(params AutomationElement[] windows)
        {
            foreach (var window in windows)
            {
                if (window != null)
                {
                    FlauiAuto.CloseWindow(window);
                }
            }
        }
    }
}